const puppeteer = require('puppeteer');
const { createWSEList, resetWSEList, fetchWSEList } = require('./puppeteer-pool.js');
const requestLog = require("./request-log.js");
// 访问次数阈值
const reqLimit = 5000
// 访问次数
let reqTimes = 0

const spider = async (url) => {
    // 标记请求次数+1
    reqTimes += 1
    // 响应头：content-type
    let contentType = "";
    // 请求次数等于请求阈值则清空浏览器实例
    if (reqTimes >= reqLimit) {
        await resetWSEList()
        // 重置请求次数
        reqTimes = 0
    }
    // 获取浏览器实例列表
    let WSE_LIST = fetchWSEList()
    if (WSE_LIST.length === 0) {
        await createWSEList()
        WSE_LIST = fetchWSEList()
    }
    let tmp = Math.floor(Math.random() * WSE_LIST.length);
    //随机获取浏览器
    let browserWSEndpoint = WSE_LIST[tmp];
    //连接
    const browser = await puppeteer.connect({
        browserWSEndpoint
    });

    //打开一个标签页
    const page = await browser.newPage();

    // Intercept network requests.
    await page.setRequestInterception(true);

    page.on('request', async (request) => {
        if (request.isInterceptResolutionHandled()) return;
        if (
            request.url().indexOf(".png") > 0 ||
            request.url().indexOf(".jpg") > 0 ||
            request.url().indexOf(".gif") > 0 ||
            request.url().indexOf(".svg") > 0 ||
            request.url().indexOf(".mp4") > 0
        ) {
            await request.abort();
        } else {
            await request.continue();
        }
    });
    page.on("response", async (response) => {
        await (contentType = response.headers()["content-type"]);
    });

    //打开网页
    try {
        await page.goto(url, {
            timeout: 60000, //连接超时时间，单位ms
            waitUntil: 'networkidle0' //网络空闲说明已加载完毕
        });
    } catch (err) {
        try {
            await page.goto(url, {
                timeout: 120000, //连接超时时间，单位ms
                waitUntil: 'networkidle0' //网络空闲说明已加载完毕
            });
        } catch (error) {
            const errorObject = {
                message: error.message,
                name: error.name,
                stack: error.stack
            };
            // 记录错误日志
            requestLog(errorObject, 'error.log')
            // 获取当前浏览器打开的tab数
            const pages = await browser.pages();
            if (pages.length > 1) {
                // 当前tab数大于1则关闭当前页面（一个浏览器至少要留一个页面，不然browser就关闭了，后面newPage就卡死了）
                await page.close();
            }
            return {
                html: '请求超时',
                contentType: 'text/html'
            };
        }
    }

    //获取渲染好的页面源码。不建议使用await page.content();获取页面，因为在我测试中发现，页面还没有完全加载。就获取到了。页面源码不完整。也就是动态路由没有加载。vue路由也配置了history模式
    const html = await page.evaluate(() => {
        return document.documentElement.outerHTML
    });
    // 获取当前浏览器打开的tab数
    const pages = await browser.pages();
    if (pages.length > 1) {
        // 当前tab数大于1则关闭当前页面（一个浏览器至少要留一个页面，不然browser就关闭了，后面newPage就卡死了）
        await page.close();
    }
    return {
        html: html || '获取html内容失败',
        contentType
    };
}

module.exports = spider;
